package com.gzhryc.shared_device.oem.code.agent.services;

import java.sql.SQLException;
import java.util.Date;
import java.util.List;

import com.gzhryc.common.ClassTools;
import com.gzhryc.common.StringTools;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.Conditions;
import com.gzhryc.jdbc.JdbcSession;
import com.gzhryc.jdbc.MultiDBTools;
import com.gzhryc.shared_device.base.enums.WalletOperateEnum;
import com.gzhryc.shared_device.base.models.OperateInfo;
import com.gzhryc.shared_device.oem.code.agent.dao.AgentReferrerWalletDao;
import com.gzhryc.shared_device.oem.code.agent.dao.db.AgentReferrerWallet;
import com.gzhryc.shared_device.oem.code.agent.services.dto.AgentReferrerWalletSearch;
import com.gzhryc.shared_device.oem.code.user.dao.db.User;
import com.gzhryc.shared_device.oem.code.user.dao.db.UserWallet;
import com.gzhryc.shared_device.oem.code.user.services.UserService;
import com.gzhryc.shared_device.oem.code.user.services.UserWalletService;

public class AgentReferrerWalletService {

    static Logger log = Logger.getLogger(AgentReferrerWalletService.class);

    public static AgentReferrerWalletService self() {
        return MultiDBTools.getService(AgentReferrerWalletService.class, true);
    }

    public static AgentReferrerWalletService self(String jdbcKey) {
        return MultiDBTools.getService(jdbcKey, AgentReferrerWalletService.class, true);
    }

    AgentReferrerWalletDao dao;

    public AgentReferrerWalletService(String jdbcKey) {
        this.dao = new AgentReferrerWalletDao(jdbcKey);
    }

    public List<AgentReferrerWallet> findBySearch(AgentReferrerWalletSearch search, Integer pageNo, Integer pageLimit){
        Conditions conditions = dao.buildConditions(search);
        try {
            return dao.findByCondition(conditions,pageNo,pageLimit);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return null;
    }
    
    public List<AgentReferrerWallet> findJoinByReferrerUserId(Long referrerUserId){
    	if(referrerUserId != null) {
    		Conditions conditions = new Conditions(AgentReferrerWallet.class);
    		conditions.and().is("referrerUserId", referrerUserId);
    		
    		try {
				return dao.findJoinByCondition(conditions);
			} catch (SQLException e) {
				log.error(e.getMessage(), e);
			}
    	}
    	return null;
    }

    public List<AgentReferrerWallet> findJoinByUserKeys(Long userId, Long referrerUserId){
        if(userId != null && referrerUserId != null){
            Conditions conditions = new Conditions(AgentReferrerWallet.class);
            conditions.and().is("userId",userId);
            conditions.and().is("referrerUserId",referrerUserId);

            try {
                return dao.findJoinByCondition(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return null;
    }

    public AgentReferrerWallet getByKeys(Long userId, Long referrerUserId,Long accountGroupId){
        if(userId != null && referrerUserId != null && accountGroupId != null) {
            Conditions conditions = new Conditions(AgentReferrerWallet.class);
            conditions.and().is("userId",userId);
            conditions.and().is("referrerUserId",referrerUserId);
            conditions.and().is("accountGroupId",accountGroupId);

            try {
                return dao.get(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    public AgentReferrerWallet getJoinByKeys(Long userId, Long referrerUserId,Long accountGroupId){
        if(userId != null && referrerUserId != null && accountGroupId != null) {
            Conditions conditions = new Conditions(AgentReferrerWallet.class);
            conditions.and().is("userId",userId);
            conditions.and().is("referrerUserId",referrerUserId);
            conditions.and().is("accountGroupId",accountGroupId);

            try {
                return dao.getJoin(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    public boolean add(AgentReferrerWallet wallet){
        wallet.setCreateDate(new Date());
        try {
            return dao.insert(wallet) > 0;
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return false;
    }

    public synchronized boolean reduceMoney(Long userId, Long referrerUserId,Long accountGroupId, Long money, OperateInfo operateInfo) throws LogicException {
    	if(money <= 0) {
    		throw new LogicException("金额必须大于0");
    	}
    	AgentReferrerWallet wallet = this.getByKeys(userId,referrerUserId,accountGroupId);
        if (wallet == null) {
            throw new LogicException("钱包未启用");
        }
        // 检查金额是否够扣除
        if (wallet.getMoney() < money) {
            throw new LogicException("超过钱包余额");
        }else {
            Date date = new Date();

            Conditions condition = new Conditions(AgentReferrerWallet.class);
            condition.and().is("userId", userId);
            condition.and().is("referrerUserId",referrerUserId);
            condition.and().is("accountGroupId", accountGroupId);
            condition.and().is("money", wallet.getMoney());
            condition.and().is("lastUpdateDate", wallet.getLastUpdateDate());

            AgentReferrerWallet walletUpdate = new AgentReferrerWallet();
            walletUpdate.setMoney(wallet.getMoney() - money);
            walletUpdate.setLastUpdateDate(date);

            try {
                if (dao.updateNotNull(walletUpdate, condition) > 0) {
                    AgentReferrerWalletOperateService.self(date).addOperate(wallet.getUserId(),wallet.getReferrerUserId(),wallet.getAccountGroupId(),
                            WalletOperateEnum.MoneyType.Money.index(), WalletOperateEnum.Type.Reduce.index(), money, operateInfo);
                    return true;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return false;
    }

    public synchronized boolean addMoney(Long userId, Long referrerUserId,Long accountGroupId, Long money, OperateInfo operateInfo) throws LogicException {
    	if(money <= 0) {
    		throw new LogicException("金额必须大于0");
    	}
    	AgentReferrerWallet wallet = this.getByKeys(userId,referrerUserId,accountGroupId);
        if (wallet == null) {
        	wallet = new AgentReferrerWallet();
        	wallet.setUserId(userId);
        	wallet.setReferrerUserId(referrerUserId);
        	wallet.setAccountGroupId(accountGroupId);
        	this.add(wallet);
        	
        	wallet = this.getByKeys(userId,referrerUserId,accountGroupId);
        	if(wallet == null) {
        		throw new LogicException("钱包未启用");
        	}
        }
        Date date = new Date();

        Conditions condition = new Conditions(AgentReferrerWallet.class);
        condition.and().is("userId", userId);
        condition.and().is("referrerUserId",referrerUserId);
        condition.and().is("accountGroupId", accountGroupId);
        condition.and().is("money", wallet.getMoney());
        condition.and().is("lastUpdateDate", wallet.getLastUpdateDate());

        AgentReferrerWallet walletUpdate = new AgentReferrerWallet();
        walletUpdate.setMoney(wallet.getMoney() + money);
        walletUpdate.setLastUpdateDate(date);

        try {
            if (dao.updateNotNull(walletUpdate, condition) > 0) {
            	AgentReferrerWalletOperateService.self(date).addOperate(wallet.getUserId(),wallet.getReferrerUserId(),wallet.getAccountGroupId(),
                        WalletOperateEnum.MoneyType.Money.index(), WalletOperateEnum.Type.Add.index(), money, operateInfo);
                return true;
            }
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }
        return false;
    }

    public synchronized boolean transferMoneyToWithdrawal(Long userId, Long referrerUserId,Long accountGroupId, Long money, OperateInfo operateInfo) throws LogicException {
    	AgentReferrerWallet wallet = this.getByKeys(userId,referrerUserId,accountGroupId);
        if (wallet == null) {
            throw new LogicException("钱包未启用");
        }
        
        // 检查金额是否够扣除
        if (wallet.getMoney() < money) {
            throw new LogicException("超过钱包余额");
        }else {
            Date date = new Date();
            
            UserWallet userWallet = UserWalletService.self().getByKeys(referrerUserId,accountGroupId);
            if(userWallet == null){
                userWallet = new UserWallet();
                userWallet.setUserId(referrerUserId);
                userWallet.setAccountGroupId(accountGroupId);
                UserWalletService.self().add(userWallet);
            }
           
            Conditions condition = new Conditions(AgentReferrerWallet.class);
            condition.and().is("userId", userId);
            condition.and().is("referrerUserId",referrerUserId);
            condition.and().is("accountGroupId", accountGroupId);
            condition.and().is("money", wallet.getMoney());
            condition.and().is("lastUpdateDate", wallet.getLastUpdateDate());

            AgentReferrerWallet walletUpdate = new AgentReferrerWallet();
            walletUpdate.setMoney(wallet.getMoney() - money);
            walletUpdate.setWithdrawnMoney(wallet.getWithdrawnMoney() + money); //已提现金额
            walletUpdate.setLastUpdateDate(date);

            JdbcSession.begin();
            try {
                if (dao.updateNotNull(walletUpdate, condition) > 0) {
                	OperateInfo temp = ClassTools.copy(new OperateInfo(), operateInfo);
                	temp.setOperateNote("从" + userId + "的介绍人账号转入");
                    User user = UserService.self().getById(userId);
                    if(user != null) {
                    	temp.setOperateNote("从" + user.getNickname() + "(" + userId + ")的介绍人账号转入");
                    }
                    if(UserWalletService.self().addWithdrawalMoney(referrerUserId,accountGroupId,money,temp)) {
                    	if(StringTools.isBlank(operateInfo.getOperateNote())) {
                    		operateInfo.setOperateNote("转出到个人钱包提现金额");
                    	}
                    	AgentReferrerWalletOperateService.self(date).addOperate(wallet.getUserId(), wallet.getReferrerUserId(), wallet.getAccountGroupId(),
                                WalletOperateEnum.MoneyType.Money.index(), WalletOperateEnum.Type.Reduce.index(), money, operateInfo);
                        JdbcSession.commit();
                        return true;
                    }
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            } finally {
                JdbcSession.end();
            }
        }
        return false;
    }

}
